/*
  Part of the MasterTool3D project - http://code.google.com/p/master-tool-3d

  Copyright (c) 2011 Ingo Pueschl

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation, version 2.1.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General
  Public License along with this library; if not, write to the
  Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  Boston, MA  02111-1307  USA
*/

package techjit.gfx.plugins.swe;

import processing.core.PApplet;
import techjit.gfx.core.GFX_Node;
import techjit.gfx.core.GFX_Scene;
import techjit.gfx.plugins.swe.drawing.BasicDrawer;
import techjit.gfx.plugins.swe.drawing.FancyDrawer;
import techjit.gfx.util.PU;
import techjit.gfx.util.geo.Dimensions;
import techjit.gfx.util.geo.Vector;
import techjit.util.LM;
import techjit.util.LogManager;
import techjit.util.RP;
import techjit.util.RuntimeParams;

public abstract class SWE_Element extends GFX_Node {

	// ENUMS
	public enum VisibilityEnum {
		PUBLIC, DEFAULT, PROTECTED, PRIVATE
	}

	// FIELDS
	String name = "";

	protected VisibilityEnum visibilityProperty = VisibilityEnum.DEFAULT;

	protected boolean staticProperty = false;
	protected boolean finalProperty = false;
	protected boolean abstractProperty = false;
	protected int sizeInByte = 0;
	protected int linesOfCode = 0;

	// CONSTRUCTORS
	public SWE_Element(GFX_Scene rootScene) {
		// head
		super(rootScene);

		// body
		changeLocalDimensions(new Dimensions(1));
	}

	// METHODS
	@Override
	public void changeLocalDimensions(Dimensions dimensions) {
		super.changeLocalDimensions(dimensions);
	}

	@Override
	public void draw(PApplet p) {
		p.pushMatrix();
		p.pushStyle();
		{
			super.draw(p);
			if (RuntimeParams.SHOW__SWE_ELEMENTS) {
				switch (RuntimeParams.DRAWING__SWE_ELEMENT_STYLE) {
				case 1:
					p.stroke(RuntimeParams.COLOR__RED);
					PU.line(p, getLocalPosition(new Vector(.5f, .5f, 0)),
							getLocalPosition(new Vector(.75f, .5f, 0)));
					p.stroke(RuntimeParams.COLOR__GREEN);
					PU.line(p, getLocalPosition(new Vector(.5f, .5f, 0)),
							getLocalPosition(new Vector(.5f, .75f, 0)));
					p.stroke(RuntimeParams.COLOR__BLUE);
					PU.line(p, getLocalPosition(new Vector(.5f, .5f, 0)),
							getLocalPosition(new Vector(.5f, .5f, .25f)));

					if (this instanceof SWE_Class) {
						p.stroke(RuntimeParams.COLOR__DARK_GREEN);
					}
					else if (this instanceof SWE_ClassFile) {
						p.stroke(RP.COLOR__WHITE);
					}
					else if (this instanceof SWE_Constructor) {
						p.stroke(RP.COLOR__DIRTY_GREEN);
					}
					else if (this instanceof SWE_Field) {
						p.stroke(RuntimeParams.COLOR__DIRTY_RED);
					} 
					else if (this instanceof SWE_Interface) {
						p.stroke(RP.COLOR__BLUE);
					}
					else if (this instanceof SWE_Method) {
						p.stroke(RuntimeParams.COLOR__DIRTY_YELLOW);
					} 
					else if (this instanceof SWE_Package) {
						p.stroke(RuntimeParams.COLOR__GREENISH_RED);
					}
					else {
						LM.errorALL("Invalid: " + this);
					}
					PU.diamond(p, getLocalPosition(new Vector(1, 1, 1)));
					break;
				case 2:
					BasicDrawer.draw(p, this);
					break;
				case 3:
					p.stroke(0xFF333333);
					p.strokeWeight(3);
					if (this instanceof SWE_Package) {
						p.fill(RuntimeParams.COLOR__GREENISH_RED);
					} else if (this instanceof SWE_Class) {
						p.fill(RuntimeParams.COLOR__DARK_GREEN);
					} else if (this instanceof SWE_Method) {
						p.fill(RuntimeParams.COLOR__DIRTY_YELLOW);
					} else {
						p.fill(RuntimeParams.COLOR__DIRTY_RED);
					}
					// PU.diamond(p, getLocalPosition(new Vector(1, 1, 1)));
					int branch = 1;
					switch (branch) {
					case 0:
						PU.box(p, getLocalPosition(new Vector(.1f)),
								getLocalPosition(new Vector(.9f)));
						break;
					case 1:
						PU.box(p, getLocalPosition(new Vector(0)),
								getLocalPosition(new Vector(1)));
						break;
					}
					break;
				case 4:
					FancyDrawer.draw(p, this);
					break;
				default:
					LogManager
							.warningALL("Specified swe element style does not exist!");
					break;
				}
			}
		}
		p.popMatrix();
		p.popStyle();
	}

	@Override
	public Vector getLocalPosition(Vector vector) {
		return super.getLocalPosition(vector);
	}

	public String getName() {
		return name;
	}

	public boolean isAbstract() {
		return abstractProperty;
	}

	public boolean isDefault() {
		if (visibilityProperty == VisibilityEnum.DEFAULT) {
			return true;
		} else {
			return false;
		}
	}

	public boolean isFinal() {
		return finalProperty;
	}

	public boolean isPrivate() {
		if (visibilityProperty == VisibilityEnum.PRIVATE) {
			return true;
		} else {
			return false;
		}
	}

	public boolean isProtected() {
		if (visibilityProperty == VisibilityEnum.PROTECTED) {
			return true;
		} else {
			return false;
		}
	}

	public boolean isPublic() {
		if (visibilityProperty == VisibilityEnum.PUBLIC) {
			return true;
		} else {
			return false;
		}
	}

	public boolean isStatic() {
		return staticProperty;
	}

	@Override
	public void log() {
		LogManager.logALL("<SWE_Element>");
		LogManager.indent();
		{
			LogManager
					.logALL("visibilityProperty = " + this.visibilityProperty);
			LogManager.logALL("staticProperty = " + this.staticProperty);
			LogManager.logALL("finalProperty = " + this.finalProperty);
			LogManager.logALL("abstractProperty = " + this.abstractProperty);
			LogManager.logALL("linesOfCodes = " + this.linesOfCode);
			LogManager.logALL("sizeInByte = " + this.sizeInByte);
			super.log();
		}
		LogManager.deindent();
	}

	public void setAbstract() {
		abstractProperty = true;
	}

	public void setDefault() {
		visibilityProperty = VisibilityEnum.DEFAULT;
	}

	public void setFinal() {
		finalProperty = true;
	}

	public void setLinesOfCode(int linesOfCode) {
		this.linesOfCode = linesOfCode;
	}

	public void setName(String name) {
		this.name = name;
	}

	public void setPrivate() {
		visibilityProperty = VisibilityEnum.PRIVATE;
	}

	public void setProtected() {
		visibilityProperty = VisibilityEnum.PROTECTED;
	}

	public void setPublic() {
		visibilityProperty = VisibilityEnum.PUBLIC;
	}

	public void setSizeInByte(int sizeInByte) {
		this.sizeInByte = sizeInByte;
	}

	public void setStatic() {
		staticProperty = true;
	}

}
